import $ from 'jquery'
import '@/js/select'
import '@/lib/jRange/jquery.range-min'
import '@/lib/jsrender.min'


/**
 * DiyConfig 说明
 * @author King
 * @requires 
 *   src/js/select
 *   src/lib/jRange/jquery.range
 *   src/lib/jsrender
 * @param
 *   {jsonstr} 页面生成的参数
 * @var
 *   {params} 根据该参数，生成 dropdown
 *   {selectTemplate} 生成 dropdown的模版
 *   {rageConfig} 根据该参数，配置 jRange
 *   {hostConfig} 不同类型主机的参数，根据该参数，点击切换不同类型时代入
 *   {userConfig} 用户选择的当前配置
 *   {priceConfig} 用以计算价格的参数
 * @method
 *   {init} 初始化 DiyConfig ，包括：
 *          1、初始化 jRange ，并预设“商务型”配置
 *          2、生成选择“操作系统”“线路”“储存模式”的 dropdown
 *          3、更新价钱
 *          4、绑定事件
 *   {getOS} {getDisktype} {getRoom} 分别为得到“操作系统”“储存方式”“线路”
 *                                   dropdown 的参数，并传入 render 方法生成 dropdown
 *   {dropdown} 返回$(dropwodn)
 *   {selectPreset} 切换不同类型主机的方法
 *   {updateUserConfig} 更新用户当前配置的方法
 *   {updatePrice} 更新价钱的方法
 */         
function DiyConfig(jsonstr) {
  let self = this
  let $cpu = $('#range-cpu'),
      $cpuLabel = $('#range-cpu-value'),
      $ram = $('#range-ram'),
      $ramLabel = $('#range-ram-value'),
      $bandWidth = $('#range-bandwidth'),
      $bandWidthLabel = $('#range-bandwidth-value'),
      $hardDisk = $('#range-harddisk'),
      $hardDiskLabel = $('#range-harddisk-value'),
      $buycount = $('#buycount'),
      $total = $('#total')

  // 下拉选择的参数
  let params = {
    os: jsonstr.os,
    room: jsonstr.room,
    disktype: jsonstr.disktype,
  }
  // range参数
  let rangeConfig = {
    cpu: {
      from: 0,
      to: 6,
      step: 1,
      width: 640,
      scale: ['1核', '2核', '4核', '8核', '12核', '16核', '32核'],
      showLabels: false,
      showScale: true,
      snap: true,
      theme: 'theme-yb',
      onstatechange: function (value) {
        self.updateUserConfig({cpu: rangeConfig.cpu.scale[value]})
        $cpuLabel.text(rangeConfig.cpu.scale[value])
        $cpu.parent('.config-input')[value == 0 ? 'addClass' : 'removeClass']('error')

        priceConfig.cpu = jsonstr.cpu.split(';')[value].split(':')[priceConfig.duration == 'month' ? 1 : 4]
        self.updatePrice()
      }
    },
    ram: {
      from: 0,
      to: 11,
      step: 1,
      width: 640,
      scale: ['0.5G', '1G', '2G', '3G', '4G', '6G', '8G', '12G', '16G', '32G', '64G', '128G'],
      showLabels: false,
      showScale: true,
      snap: true,
      theme: 'theme-yb',
      onstatechange: function (value) {
        self.updateUserConfig({ram: rangeConfig.ram.scale[value]})
        $ramLabel.text(rangeConfig.ram.scale[value])
        $ram.parent('.config-input')[value == 0 ? 'addClass' : 'removeClass']('error')
        priceConfig.ram = jsonstr.ram.split(';')[value].split(':')[priceConfig.duration == 'month' ? 1 : 4]
        self.updatePrice()
      }
    },
    hardDisk: {
      from: 50,
      to: 1000,
      step: 10,
      width: 640,
      scale: ['50G', '1000G'],
      showLabels: false,
      showScale: true,
      snap: true,
      theme: 'theme-yb',
      onstatechange: function (value) {
        self.updateUserConfig({hardDisk: value+'G'})
        $hardDiskLabel.text(value + 'G')
        let step = jsonstr.data.split(':')[0]
        let modulus = jsonstr.data.split(':')[priceConfig.duration == 'month' ? 1 : 4]
        priceConfig.data = value > 50 ? (value-50)/step*modulus : 0
        if( priceConfig.disktype == 'ssd' ) {
          let duration = $('select[name="duration"] option:selected').val()[0]
          priceConfig.data = priceConfig.data * 3;
          priceConfig.data = priceConfig.duration == 'year' ? priceConfig.data + 300 : priceConfig.data + 30 * duration
        }
        self.updatePrice()
      }
    },
    bandWidth: {
      from: 0,
      to: 200,
      step: 1,
      width: 640,
      scale: ['0M', '200M'],
      showLabels: false,
      showScale: true,
      snap: true,
      theme: 'theme-yb',
      onstatechange: function (value) {
        self.updateUserConfig({bandWidth: value+'M'})
        $bandWidthLabel.text(value + 'M')
        $bandWidth.parent('.config-input')[value == 0 ? 'addClass' : 'removeClass']('error')

        let param = jsonstr.flux.split(';')
        param.forEach(item => {
          let array = item.split(':')
          if( array[0] == priceConfig.room ){
            let flux = array[priceConfig.duration == 'month' ? 1 : 4],
                flux_min = array[priceConfig.duration == 'month' ? 5 : 8],
                flux_max = array[priceConfig.duration == 'month' ? 9 : 12]
            priceConfig.flux = value <= 5 ? parseFloat(flux_min) + parseFloat(flux)*value : parseFloat(flux_min) + parseFloat(flux)*5 + parseFloat(flux_max)*(value-5)
          }
        });
        self.updatePrice()
      }
    }
  }
  // 不同类型主机参数
  let hostConfig = {
    'basic': {
      title: "入门型",
      cpu: '1',
      ram: '1',
      hardDisk: '80',
      bandWidth: '2'
    },
    'standard': {
      title: "标准型",
      cpu: '1',
      ram: '2',
      hardDisk: '110',
      bandWidth: '3'
    },
    'business': {
      title: "商务型",
      cpu: '2',
      ram: '4',
      hardDisk: '130',
      bandWidth: '4'
    },
    'comfortable': {
      title: "舒适型",
      cpu: '2',
      ram: '4',
      hardDisk: '230',
      bandWidth: '5'
    },
    'enterprise': {
      title: "企业型",
      cpu: '3',
      ram: '6',
      hardDisk: '330',
      bandWidth: '8'
    },
    'luxury': {
      title: "豪华型",
      cpu: '4',
      ram: '7',
      hardDisk: '530',
      bandWidth: '10'
    }
  }
  // 右边显示的当前参数
  let userConfig = {
    title: "商务型",
    cpu: '4核',
    ram: '4G',
    hardDisk: '130G',
    bandWidth: '4M',
    os: '请选择操作系统',
    room: '华中BGP(性价比高！BGP多线云服务器,独立IP)',
    disktype: '分布式集群存储',
    buycount: 1,
    duration: '一个月',
    agreement: true
  }
  // 影响价钱的参数
  let priceConfig = {
    cpu: null,
    ram: null,
    flux: null,
    data: null,
    room: null,
    disktype: null,
    buycount: 1,
    // 按月，和按年购买，是不同的参数，默认按月
    duration: 'month'
  }
  // 下拉菜单模版
  let selectTemplate = `
  <div class="ui-selection" data-plugin="select">
    <select></select>
    <div class="text"></div>
    <ul class="ui-selection-options"></ul>
  </div>
  `

  DiyConfig.prototype.init = function () {
    let self = this

    $cpu.jRange(rangeConfig.cpu);
    $ram.jRange(rangeConfig.ram);
    $hardDisk.jRange(rangeConfig.hardDisk);
    $bandWidth.jRange(rangeConfig.bandWidth);

    this.getRoom()
    this.getOS()
    this.getDisktype()

    this.selectPreset(hostConfig.business)
    this.updatePrice()
    
    // bind event
    $buycount.on('blur', function() {
      var value = $(this).val();
      value = /^\d+$/.test(value) ? +value : 1
      if (value < 1) {
          value = 1;
      } else if (value > 100) {
          value = 100;
      }
      $(this).val(value)
      priceConfig.buycount = value
      self.updateUserConfig({buycount: value})
      self.updatePrice()
    })

    $('#js-preset-change').on('click', '>.button', function(e){
      e.preventDefault()
      $(this).addClass('active').siblings().removeClass('active')
      let href = $(this).attr('href').replace('#', '')
      let param = hostConfig[href]
      self.selectPreset(param)
    })

    $('[data-plugin="select"]').on('onSelect', function(e){
      let param = {}
      param[e.selectName] = $(e.relatedTarget).text()
      self.updateUserConfig(param)
      // 如果更改了线路，则更新价格
      if( e.selectName == 'room') {
        priceConfig.room = $(e.relatedTarget).data('value')
        let bandwidth = $bandWidth.val()
        let param = jsonstr.flux.split(';')
        param.forEach(item => {
          let array = item.split(':')      
          if( array[0] == priceConfig.room ){
            let flux = array[priceConfig.duration == 'month' ? 1 : 4],
                flux_min = array[priceConfig.duration == 'month' ? 5 : 8],
                flux_max = array[priceConfig.duration == 'month' ? 9 : 12]
            priceConfig.flux = bandwidth <= 5 ? parseFloat(flux_min) + parseFloat(flux)*bandwidth : parseFloat(flux_min) + parseFloat(flux)*5 + parseFloat(flux_max)*(bandwidth-5)
          }
        });
        self.updatePrice()
      }
      // 如果更改了储存模式，则更新价格
      if( e.selectName == 'disktype'){
        priceConfig.disktype = $(e.relatedTarget).data('value')
        let dataValue = $hardDisk.val()
        let step = jsonstr.data.split(':')[0]
        let modulus = jsonstr.data.split(':')[priceConfig.duration == 'month' ? 1 : 4]
        priceConfig.data = dataValue > 50 ? (dataValue-50)/step*modulus : 0
        
        if( priceConfig.disktype == 'ssd' ) {
          let duration = $('select[name="duration"] option:selected').val()[0]
          priceConfig.data = priceConfig.data * 3;
          priceConfig.data = priceConfig.duration == 'year' ? priceConfig.data + 300 : priceConfig.data + 30 * duration
        }

        self.updatePrice()
      }
      // 如果更改了购买时长，则更新价格
      if( e.selectName == 'duration'){
        priceConfig.duration = $(e.relatedTarget).data('value').indexOf('m') < 0 ? 'year' : 'month' 
        let key = priceConfig.duration == 'month' ? 1 : 4

        let cpuValue = $cpu.val(),
            ramValue = $ram.val(),
            dataValue = $hardDisk.val(),
            fluxValue = $bandWidth.val()

        // 更改cpu计算参数
        priceConfig.cpu = jsonstr.cpu.split(';')[cpuValue].split(':')[key]

        // 更改内存计算参数
        priceConfig.ram = jsonstr.ram.split(';')[ramValue].split(':')[key]

        // 更改硬盘计算参数
        let step = jsonstr.data.split(':')[0]
        let modulus = jsonstr.data.split(':')[key]
        priceConfig.data = dataValue > 50 ? (dataValue-50)/step*modulus : 0
        if( priceConfig.disktype == 'ssd' ) {
          let duration = $('select[name="duration"] option:selected').val()[0]
          priceConfig.data = priceConfig.data * 3;
          priceConfig.data = priceConfig.duration == 'year' ? priceConfig.data + 300 : priceConfig.data + 30 * duration
        }

        // 更改带宽计算参数
        let param = jsonstr.flux.split(';')
        param.forEach(item => {
          let array = item.split(':')
          if( array[0] == priceConfig.room ){
            let flux = array[priceConfig.duration == 'month' ? 1 : 4],
                flux_min = array[priceConfig.duration == 'month' ? 5 : 8],
                flux_max = array[priceConfig.duration == 'month' ? 9 : 12]
            priceConfig.flux = fluxValue <= 5 ? parseFloat(flux_min) + parseFloat(flux)*fluxValue : parseFloat(flux_min) + parseFloat(flux)*5 + parseFloat(flux_max)*(fluxValue-5)
          }
        })

        self.updatePrice()
      }
      if( e.selectName == 'os' ){
        $('#select-os')[$(e.relatedTarget).data('value') == '' ? 'addClass' : 'removeClass']('error')
      }
    })

    $('#agreement').on('change', function(){
      userConfig.agreement = $(this).prop('checked')
      $('.agreement-label')[userConfig.agreement ? 'removeClass' : 'addClass']('error')
    })

    $('#js-submit').on('click', function(){
      let checkOS = $('select[name="os"] option:selected').val() == "" ? false : true
      if( userConfig.agreement && checkOS ){
        $('#config-form').submit()
      }else{
        $('#select-os')[checkOS ? 'removeClass' : 'addClass']('error')
        $('.agreement-label')[userConfig.agreement ? 'removeClass' : 'addClass']('error')
      }
    })

  }

  DiyConfig.prototype.getOS = function () {
    let os = params.os
    let osParams = []
    let selector = '#select-os'
    let name = 'os'
    $(os).find('option').each(function (i, ele) {
      osParams.push({
        value: $(this).val(),
        text: $(this).text(),
        isCheck: $(this).attr('selected') == 'selected' ||
          $(this).val() == '' ? true : false
      })
    })

    osParams.sort(function (a, b) {
      return b.value.charCodeAt(0) - a.value.charCodeAt(0)
    })

    this.render(selector, name, osParams)
  }

  DiyConfig.prototype.getDisktype = function () {
    let diskType = params.disktype
    let distTypeParams = []
    let selector = '#select-disktype'
    let name = 'disktype'
    $(diskType).each(function (i, ele) {
      distTypeParams.push({
        value: $(this).find('input').val(),
        text: $(this).find('span').text(),
        isCheck: $(this).find('input').attr('checked') == 'checked' ? true : false
      })
    })
    priceConfig.disktype = $(diskType).find('input:checked').val()
    this.render(selector, name, distTypeParams)
  }

  DiyConfig.prototype.getRoom = function () {
    let room = params.room
    let roomParams = []
    let selector = '#select-room'
    let name = 'room'
    $(room).each(function (i, ele) {
      roomParams.push({
        value: $(this).find('input').val(),
        text: $(this).find('a').text(),
        isCheck: $(this).find('input').attr('checked') == 'checked' ? true : false
      })
    })
    priceConfig.room = $(room).find('input:checked').val()
    this.render(selector, name, roomParams)
  }

  DiyConfig.prototype.render = function (selector, name, params) {
    let $dropdown = this.dropdown()

    let $select = $dropdown.find('select')
    let $menu = $dropdown.find('.ui-selection-options')
    let $text = $dropdown.find('.text')

    $select.attr('name', name)

    let options = ''
    let menu = ''
    params.forEach(item => {
      if (item.isCheck) {
        options += `<option value="${item.value}" selected>${item.text}</option>`
        menu += `<li class="selected" data-value="${item.value}">${item.text}</li>`
      } else {
        options += `<option value="${item.value}">${item.text}</option>`
        menu += `<li data-value="${item.value}">${item.text}</li>`
      }
    });
    $select.append(options)
    $menu.append(menu)

    $dropdown.uiSelect()

    $(selector).append($dropdown)
  }

  DiyConfig.prototype.dropdown = function () {
    return $(selectTemplate)
  }

  DiyConfig.prototype.selectPreset = function(param){
    $cpu.jRange('setValue', param.cpu);
    $ram.jRange('setValue', param.ram);
    $hardDisk.jRange('setValue', param.hardDisk);
    $bandWidth.jRange('setValue', param.bandWidth);
    this.updateUserConfig({title: param.title})
    this.updatePrice()
  }

  DiyConfig.prototype.updateUserConfig = function(param){
    for(const key in param){
      userConfig[key] = param[key]
    }
    var html = $("#js-render").render(userConfig);
    $("#user-config").html(html);
    this.updatePrice()
  }

  DiyConfig.prototype.updatePrice = function(){
    let duration = $('select[name="duration"] option:selected').val()[0]
    let price = ((parseFloat(priceConfig.cpu) + parseFloat(priceConfig.data) + parseFloat(priceConfig.ram) + parseFloat(priceConfig.flux)) * duration) * priceConfig.buycount
    price = isNaN(price) ? 0 : price
    $total.text(price)
  }
}
module.exports = DiyConfig